#include "corexmlparser.h"
#include <QDomDocument>
#include <QDomNode>
#include <QDebug>
#include <QSslSocket>
#include "corexmlhandler.h"
#include <QDomElement>


CoreXMLParser::CoreXMLParser(QSslSocket* sock,QObject *parent) :
   QObject(parent), QXmlSimpleReader()
{
    m_xmlHandler = new CoreXMLHandler();
    this->setContentHandler(m_xmlHandler);
    this->setErrorHandler(m_xmlHandler);

    QObject::connect(m_xmlHandler,SIGNAL(malformedXML()),
                     this,SLOT(malformedXML()));
    QObject::connect(m_xmlHandler,SIGNAL(readyParse(QDomNode)),
                     this,SLOT(parseElement(QDomNode)));

    m_username = "";
    m_socket = sock;

    // we can't start parsing here direclty
    // because the call to parse() does not return
    // thus connecting with Qt::QueuedConnection
    // allows us to finish this function and process
    // the signal as soon as the EventHandler is returned.
    QObject::connect(this,SIGNAL(startParsing()),this,SLOT(startParser()),Qt::QueuedConnection);
    emit startParsing();
}

void CoreXMLParser::startParser()
{
    parse(new QXmlInputSource(m_socket),true);
}



void CoreXMLParser::parseElement(QDomNode e)
{
    qDebug() << "parseElement: "<< e.toElement().tagName();
    if(e.toElement().tagName().toLower() == "auth")
        parseAuthRequest(e);
    else if (e.toElement().tagName().toLower() == "message")
        parseMessage(e);
    else if(e.toElement().tagName().toLower() == "connection")
        parseConnection(e);
    else if (e.toElement().tagName().toLower() == "roster")
        parseRoster(e);
    else
        emit malformedXML("invalid top level Element");
}


void CoreXMLParser::parseMessage(QDomNode e)
{

}


void CoreXMLParser::parseConnection(QDomNode e)
{
    qDebug() << "parsing connection tag";
    QDomElement c = e.firstChildElement().toElement();
    if(c.tagName().toLower() == "state")
    {
        if(!c.hasAttribute("type"))
        {
            emit malformedXML("connection::state received without type");
            return;
        }
        if(c.attribute("type").toLower() == "get")
        {
            if(!c.hasAttribute("jid") || c.attribute("jid") == "all")
            {
                emit getConnectionState(m_username);
            }
            else
            {
                emit getConnectionState(m_username,c.attribute("jid"));
            }
        }
        else if (c.attribute("type").toLower() == "set")
        {
            QString jid = c.attribute("jid","");
            if(jid == "")
            {
                emit malformedXML("no jid given for setting connection state");
                return;
            }
            QString state = c.attribute("value","").toLower();
            if (state == "")
            {
                emit malformedXML("no state provided for setting connection state");
                return;
            }

            emit setConnectionState(m_username, jid, state);
            return;
        }
        else
        {
            emit malformedXML("invalid value of type attribute when parsing a connection");
            return;
        }
    }
    else
    {
        emit malformedXML( "unknown connection child element");
    }
}


void CoreXMLParser::parseRoster(QDomNode e)
{

}

void CoreXMLParser::parseAuthRequest(QDomNode e)
{
    qDebug() << "parsing Auth Request";
    if (m_username != "")
    {
        emit malformedXML("trying to auth more than once");
        return;
    }
    if(e.childNodes().count() < 2)
    {
        emit malformedXML("less than 2 child nodes supplied for auth");
        return;
    }
    QString password;
    QDomElement u = e.firstChildElement("username");
    if (u.isNull())
    {
        emit malformedXML(" No Username supplied for auth");
        return;
    }
    else
       m_username = u.text();
    QDomElement p = e.firstChildElement("password");
    if (u.isNull())
    {
        emit malformedXML("No password supplied for auth");
        return ;
    }
    else
        password = p.text();

    emit authenticationRequest(m_username,password);
}


void CoreXMLParser::malformedXML(QString err_text)
{
    qDebug() << "malformedXML: " << err_text;
    // todo: emit this through to coreserver
    //emit malformedXML();
}
